Add Geoniche. From Rick Richardson.
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 24 Nov 2003 15:42:05 +0000 (15:42 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Mon, 24 Nov 2003 15:42:05 +0000 (15:42 +0000)
gpsbabel/Makefile
gpsbabel/geoniche.c [new file with mode: 0644]
gpsbabel/vecs.c

index 0183705d4c0c1ef8269d23890705749abf9f3caf..d0bfa51322b6f2abd8a5f9196c7bfb62929247d3 100644 (file)
@@ -18,7 +18,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \
        gpsutil.o pcx.o cetus.o copilot.o gpspilot.o magnav.o \
        psp.o holux.o garmin.o tmpro.o tpg.o \
        xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o \
-       gpilots.o saroute.o navicache.o psitrex.o
+       gpilots.o saroute.o navicache.o psitrex.o geoniche.o
 
 FILTERS=position.o duplicate.o arcdist.o polygon.o
 
diff --git a/gpsbabel/geoniche.c b/gpsbabel/geoniche.c
new file mode 100644 (file)
index 0000000..5437f6e
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+    Read and write GeoNiche files.
+
+    Copyright (C) 2003 Rick Richardson <rickr@mn.rr.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "coldsync/palm.h"
+#include "coldsync/pdb.h"
+
+#define MYNAME         "Geoniche"
+#define MYTYPE                 0x50454e44      /* PEND */
+#define MYCREATOR      0x47656f4e      /* GeoN */
+
+static FILE            *FileIn;
+static FILE            *FileOut;
+static const char      *FilenameOut;
+static struct pdb      *PdbOut;
+
+static char            Rec0Magic[] = "68000NV4Q2";
+
+/*
+ * Conversions between gc.com ID's and GID's
+ */
+static char    GcSet[] = "0123456789ABCDEFGHJKMNPQRTVWXYZ";
+static int     GcOffset = 16 * 31 * 31 * 31 - 65536;
+
+static int
+gid2id(char *gid)
+{
+    char       *p;
+    int                i, val;
+
+    if (strncmp(gid, "GC", 2) != 0)
+       return -1;
+    if (strlen(gid) != 6)
+       return -1;
+    gid += 2;
+
+    if (strcmp(gid, "G000") < 0)
+       return strtol(gid, NULL, 16);
+
+    for (val = i = 0; i < 4; ++i)
+    {
+       val *= 31;
+       p = strchr(GcSet, gid[i]);
+       if (!p) return -1;
+       val += p - GcSet;
+    }
+    return val - GcOffset;
+}
+
+static void
+id2gid(char gid[6+1], int id)
+{
+    gid[0] = 0;
+    if (id < 0)
+       return;
+    else if (id < 65536)
+       snprintf(gid, 6+1, "GC%04X", id);
+    else
+    {
+       int     i;
+
+       id += GcOffset;
+       gid[0] = 'G';
+       gid[1] = 'C';
+       for (i = 5; i >= 2; --i) {
+           gid[i] = GcSet[id%31];
+           id /= 31;
+       }
+       gid[6] = 0;
+       if (id)
+           gid[0] = 0;
+    }
+    return;
+}
+
+static void
+rd_init(const char *fname)
+{
+    FileIn = fopen(fname, "rb");
+    if (FileIn == NULL)
+       fatal(MYNAME ": Cannot open %s for reading\n", fname);
+}
+
+static void
+rd_deinit(void)
+{
+    fclose(FileIn);
+}
+
+static void
+wr_init(const char *fname)
+{
+    FileOut = fopen(fname, "wb");
+    FilenameOut = fname;
+    if (FileOut == NULL)
+       fatal(MYNAME ": Cannot open %s for writing\n", fname);
+}
+
+static void
+wr_deinit(void)
+{
+    fclose(FileOut);
+}
+
+static char *
+field(char **pp, int *lenp)
+{
+    int                len = *lenp;
+    char       *p = *pp;
+    char       *dp, *dbuf;
+    int                state = 0;
+
+    if (len == 0 || *p == 0)
+       return NULL;
+
+    dbuf = dp = xmalloc(len);
+    while (len)
+    {
+       char    ch;
+
+       ch = *p++;
+       --len;
+       if (ch == 0 || len == 0)
+           break;
+       switch (state)
+       {
+       case 0:
+           if (ch == '\\')
+               state = 1;
+           else if (ch == ',')
+               goto eof;
+           else
+               *dp++ = ch;
+           break;
+       default:
+           *dp++ = ch;
+           state = 0;
+           break;
+       }
+    }
+eof:
+    *dp++ = 0;
+    dbuf = xrealloc(dbuf, dp - dbuf);
+    /* fprintf(stderr, "<%.8s> dbuf=%x, len=%d\n", *pp, dbuf, len); */
+    *pp = p;
+    *lenp = len;
+    return dbuf;
+}
+
+static void
+data_read(void)
+{
+    struct pdb *pdb;
+    struct pdb_record *pdb_rec;
+
+    if (NULL == (pdb = pdb_Read(fileno(FileIn))))
+       fatal(MYNAME ": pdb_Read failed\n");
+
+    if ((pdb->creator != MYCREATOR) || (pdb->type != MYTYPE))
+       fatal(MYNAME ": Not a GeoNiche file.\n");
+
+    /* Process record 0 */
+    pdb_rec = pdb->rec_index.rec;
+    if (strcmp(pdb_rec->data, Rec0Magic))
+       fatal(MYNAME ": Bad record 0, not a GeoNiche file.\n");
+    pdb_rec = pdb_rec->next;
+
+    /* Process the rest of the records */
+    for (; pdb_rec; pdb_rec = pdb_rec->next)
+    {
+       waypoint        *wpt;
+       char            *vdata;
+       int             vlen;
+       char            *p;
+
+       int             id;
+       int             route_id;
+       char            *title;
+       char            *category;
+       double          lat, lon, alt;
+       char            *datestr, *timestr;
+       int             icon;
+       char            *notes;
+       char            gid[6+1];
+       struct tm       tm;
+
+       wpt = xcalloc(sizeof(*wpt), 1);
+       if (!wpt)
+           fatal(MYNAME ": Couldn't allocate waypoint.\n");
+       vdata = (char *) pdb_rec->data;
+       vlen = pdb_rec->data_len;
+
+       /* Field 1: Target */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 1.\n");
+       if (strcmp(p, "Target"))
+           fatal(MYNAME ": Can only handle Target records.\n");
+       xfree(p);
+
+       /* Field 2: Import ID number */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 2.\n");
+       id = atoi(p);
+       xfree(p);
+
+       /* Field 3: Title */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 3.\n");
+       title = p;
+
+       /* Field 4: Route ID number */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 4.\n");
+       route_id = atoi(p);
+       xfree(p);
+
+       /* Field 5: Category */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 5.\n");
+       category = p;
+
+       /* Field 6: Latitude */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 6.\n");
+       lat = atof(p);
+       xfree(p);
+
+       /* Field 7: Longitude */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 7.\n");
+       lon = atof(p);
+       xfree(p);
+
+       /* Field 8: Altitude */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 8.\n");
+       alt = atof(p);
+       xfree(p);
+
+       /* Field 9: Creation date */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 9.\n");
+       datestr = p;
+
+       /* Field 10: Creation time */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 10.\n");
+       timestr = p;
+
+       /* Field 11: Visited date */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 11.\n");
+       xfree(p);
+
+       /* Field 12: Visited time */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 12.\n");
+       xfree(p);
+
+       /* Field 13: Icon color (R G B) */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 13.\n");
+       xfree(p);
+
+       /* Field 14: icon number */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 14.\n");
+       icon = atoi(p);
+       xfree(p);
+
+       /* Field 15: unused */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 15.\n");
+       xfree(p);
+
+       /* Field 16: unused */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 16.\n");
+       xfree(p);
+
+       /* Field 17: unused */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 17.\n");
+       xfree(p);
+
+       /* Field 18: Notes */
+       p = field(&vdata, &vlen);
+       if (!p) fatal(MYNAME ": Premature EOD processing field 18.\n");
+       notes = p;
+
+       sscanf(datestr, "%d/%d/%d", &tm.tm_mon, &tm.tm_mday, &tm.tm_year);
+       tm.tm_mon -= 1;
+       tm.tm_year -= 1900;
+       sscanf(timestr, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+       wpt->creation_time = mktime(&tm);
+       xfree(datestr);
+       xfree(timestr);
+
+       id2gid(gid, id);
+       wpt->latitude = lat;
+       wpt->longitude = lon;
+       wpt->altitude = alt;
+       wpt->icon_descr = category;
+
+       if (gid[0])
+       {
+           wpt->shortname = strdup(gid);
+           wpt->description = title;
+           wpt->notes = notes;
+       }
+       else
+       {
+           wpt->shortname = strdup(title);
+           wpt->description = title;
+           wpt->notes = notes;
+       }
+
+       waypt_add(wpt);
+    } 
+    free_pdb(pdb);
+}
+
+static char *
+enscape(char *s)
+{
+    char       *buf, *d;
+
+    if (!s)
+    {
+       d =  xmalloc(1);
+       *d = 0;
+       return d;
+    }
+    buf = d = xmalloc(strlen(s) * 2 + 1);
+    for (; *s; ++s)
+    {
+       if (*s == '\\' || *s == ',')
+           *d++ = '\\';
+       *d++ = *s;
+    }
+
+    *d = 0;
+    return buf;
+}
+
+/*
+ * Attempt to map an icon description into a GeoNiche icon number
+ */
+static int
+wpt2icon(const waypoint *wpt)
+{
+    const char *desc = wpt->icon_descr;
+
+    if (!desc) return 0;
+    else if (strstr(desc, "reg")) return 43;
+    else if (strstr(desc, "trad")) return 43;
+    else if (strstr(desc, "multi")) return 44;
+    else if (strstr(desc, "offset")) return 44;
+    else if (strstr(desc, "virt")) return 45;
+    else if (strstr(desc, "loca")) return 45;
+    else if (strstr(desc, "event")) return 46;
+    else if (strstr(desc, "lett")) return 47;
+    else if (strstr(desc, "hyb")) return 47;
+    else if (strstr(desc, "unk")) return 48;
+    else if (strstr(desc, "cam")) return 49;
+    else return 0;
+}
+
+static void
+copilot_writewpt(const waypoint *wpt)
+{
+    static int         ct = 0;
+    struct pdb_record  *opdb_rec;
+    int                        vlen;
+    static int         vsize = 4096;
+    char               *vdata;
+    char               *title;
+    struct tm          tm;
+    char               datestr[10+1];
+    char               timestr[8+1];
+    char               *notes;
+    int                        id;
+
+    if (ct == 0)
+    {
+       opdb_rec = new_Record (0, 0, ct++, sizeof(Rec0Magic), Rec0Magic);              
+       if (opdb_rec == NULL)
+           fatal(MYNAME ": libpdb couldn't create record\n");
+       if (pdb_AppendRecord(PdbOut, opdb_rec))
+           fatal(MYNAME ": libpdb couldn't append record\n");
+    }
+
+    if (wpt->description[0])
+       title = enscape(wpt->description);
+    else
+       title = enscape(wpt->shortname);
+
+    id = gid2id(wpt->shortname);
+    if (id < 0)
+       id = ct;
+
+    tm = *localtime(&wpt->creation_time);
+    strftime(datestr, sizeof(datestr), "%m/%d/%Y", &tm);
+    strftime(timestr, sizeof(timestr), "%H:%M:%S", &tm);
+
+    /* Notes field MUST have soemthing in it */
+    if (!wpt->notes || wpt->notes[0] == 0)
+       notes = strdup(title);
+    else
+       notes = enscape(wpt->notes);
+
+    vdata = (char *) xmalloc(vsize);
+    if (vdata == NULL)
+       fatal(MYNAME ": libpdb couldn't get record memory\n");
+
+    for (;;)
+    {
+       vlen = snprintf(vdata, vsize,
+           "Target,%d,%s,,%s,%f,%f,%f,%s,%s,,,,%d,,,,%s"
+           , id
+           , title
+           /* route ID */
+           , "Cache" /*wpt->icon_descr*/
+           , wpt->latitude
+           , wpt->longitude
+           , wpt->altitude
+           , datestr
+           , timestr
+           /* visited date */
+           /* visited time */
+           /* icon color R G B */
+           , wpt2icon(wpt)
+           /* unused1 */
+           /* unused2 */
+           /* unused3 */
+           , notes
+           );
+
+       if (vlen > -1 && vlen < vsize)
+           break;
+
+       /* try again with more space. */
+       if (vlen > -1)
+           vsize = vlen + 1;
+       else
+           vsize *= 2;
+       vdata = (char *) xrealloc(vdata, vsize);
+       if (vdata == NULL)
+           fatal(MYNAME ": libpdb couldn't get record memory\n");
+    }
+
+    opdb_rec = new_Record (0, 0, ct++, vlen+1, vdata);        
+
+    if (opdb_rec == NULL)
+       fatal(MYNAME ": libpdb couldn't create record\n");
+    if (pdb_AppendRecord(PdbOut, opdb_rec))
+       fatal(MYNAME ": libpdb couldn't append record\n");
+
+    xfree(notes);
+    xfree(title);
+    xfree(vdata);
+}
+
+static void
+data_write(void)
+{
+    if (NULL == (PdbOut = new_pdb()))
+       fatal (MYNAME ": new_pdb failed\n");
+
+    strncpy(PdbOut->name, FilenameOut, PDB_DBNAMELEN);
+    PdbOut->name[PDB_DBNAMELEN-1] = 0;
+    PdbOut->attributes = PDB_ATTR_BACKUP;
+    PdbOut->ctime = PdbOut->mtime = time(NULL) + (49*365 + 17*366) * (60*60*24);
+    PdbOut->type = MYTYPE;
+    PdbOut->creator = MYCREATOR; 
+    PdbOut->version = 0;
+    PdbOut->modnum = 1;
+
+    waypt_disp_all(copilot_writewpt);
+    
+    pdb_Write(PdbOut, fileno(FileOut));
+
+    free_pdb(PdbOut);
+}
+
+
+ff_vecs_t geoniche_vecs =
+{
+       rd_init,
+       wr_init,
+       rd_deinit,
+       wr_deinit,
+       data_read,
+       data_write,
+       NULL
+};
index 7de8df7d28aedcda6041a9b39ef9222282b3c9aa..108d72f5df1c9ab14b4396a6f27081f7c93fdd79 100644 (file)
@@ -55,6 +55,7 @@ extern ff_vecs_t gpilots_vecs;
 extern ff_vecs_t saroute_vecs;
 extern ff_vecs_t navicache_vecs;
 extern ff_vecs_t psit_vecs;             /* MRCB */
+extern ff_vecs_t geoniche_vecs;
 
 static
 vecs_t vec_list[] = {
@@ -209,6 +210,12 @@ vecs_t vec_list[] = {
                "KuDaTa PsiTrex text",
                NULL
        },
+       {
+               &geoniche_vecs,
+               "geoniche",
+               "GeoNiche .pdb",
+               NULL
+       },
        {
                NULL,
                NULL,